在此 notebook 中,我们已经为你提供一些模板代码,要成功完成此项目,你需要实现其他功能。除此之外,不需要修改所提供的代码。标题中以(实现)开头的部分表明你必须在下面的代码块中提供其他功能。我们会在每个部分提供说明,并在以“TODO”开头的代码块中提供实现细节。请仔细阅读说明。
注意:完成所有代码实现后,最后需要将 iPython Notebook 导出为 HTML 文档。在将 notebook 导出为 HTML 前,请运行所有代码单元格,使审阅者能够查看最终实现和输出结果。然后导出 notebook,方法是:使用顶部的菜单并依次转到文件 -> 下载为 -> HTML (.html)。提交内容应该同时包含此 notebook 和完成的文档。
除了实现代码之外,还需要回答与项目和代码实现相关的问题。请仔细阅读每个问题,并在答案:下方的文本框中填写答案。我们将根据每个问题的答案以及实现代码评估你提交的项目。
注意:可以通过 Shift + Enter 键盘快捷键执行代码和标记单元格,并且可以通过双击单元格进入编辑模式,编辑标记单元格。
审阅标准还包含可选的“锦上添花”建议,可以指导你在满足最低要求的基础上改进项目。如果你打算采纳这些建议,则应该在此 Jupyter notebook 中添加代码。
在此 notebook 中,你将开发一种可用于移动应用或网络应用的算法。最终你的代码将能够将任何用户提供的图像作为输入。如果从图像中检测出小狗,该算法将大致识别出小狗品种。如果检测出人脸,该算法将大致识别出最相似的小狗品种。下图显示了最终项目的潜在示例输出(但是我们希望每个学员的算法行为都不一样。)。

在此实际应用中,你需要将一系列模型整合到一起并执行不同的任务;例如,检测图中人脸的算法与推理小狗品种的 CNN 将不一样。有很多地方都可能会出错,没有什么完美的算法。即使你的答案不完美,也可以创造有趣的用户体验。
我们将此 notebook 分成了几个独立的步骤。你可以通过以下链接浏览此 notebook。
首先下载人脸和小狗数据集:
注意:如果你使用的是 Udacity 工作区,你*不需要重新下载它们 - 它们可以在/ data文件夹中找到,如下面的单元格所示。
注意如果你使用的是 Windows 设备,建议使用 7zip 解压文件。
在下面的代码单元格中将人脸 (LFW) 数据集和小狗数据集的文件路径保存到 NumPy 数组 human_files 和 dog_files 中。
import numpy as np
from glob import glob
# load filenames for human and dog images
human_files = np.array(glob("/data/lfw/*/*"))
dog_files = np.array(glob("/data/dog_images/*/*/*"))
print('There are %d total human images.' % len(human_files))
print('There are %d total dog images.' % len(dog_files))
import cv2
import matplotlib.pyplot as plt
%matplotlib inline
# extract pre-trained face detector
face_cascade = cv2.CascadeClassifier('haarcascades/haarcascade_frontalface_alt.xml')
# load color (BGR) image
img = cv2.imread(human_files[0])
# convert BGR image to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# find faces in image
faces = face_cascade.detectMultiScale(gray)
# print number of faces detected in the image
print('Number of faces detected:', len(faces))
# get bounding box for each detected face
for (x,y,w,h) in faces:
# add bounding box to color image
cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
# convert BGR image to RGB for plotting
cv_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# display the image, along with bounding box
plt.imshow(cv_rgb)
plt.show()
在使用任何人脸检测器之前,标准做法是将图像转换为灰阶图像。detectMultiScale 函数会执行存储在 face_cascade 中的分类器并将灰阶图像当做参数。
在上述代码中,faces 是一个包含检测到的人脸的 numpy 数组,其中每行对应一张检测到的人脸。检测到的每张人脸都是一个一维数组,其中有四个条目,分别指定了检测到的人脸的边界框。数组中的前两个条目(在上述代码中提取为 x 和y)指定了左上角边界框的水平和垂直位置。数组中的后两个条目(提取为 w 和 h)指定了边界框的宽和高。
我们可以编写一个函数,如果在图像中检测到人脸,该函数将返回 True,否则返回 False。此函数称为 face_detector,参数为图像的字符串文件路径,并出现在以下代码块中。
# returns "True" if face is detected in image stored at img_path
def face_detector(img_path):
img = cv2.imread(img_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray)
return len(faces) > 0
问题 1:使用以下代码单元格测试 face_detector 函数的性能。
human_files 中的前100 张图像,有多少图像检测到了人脸? dog_files 中的前100 张图像,有多少图像检测到了人脸? 理想情况下,我们希望所有人脸图像都能检测到人脸,所有小狗图像都不能检测到人脸。我们的算法不能满足此目标,但是依然达到了可接受的水平。我们针对每个数据集的前 100 张图像提取出文件路径,并将它们存储在 numpy 数组 human_files_short 和 dog_files_short 中。
答案: (请在此单元格中填写结果和/或百分比)
from tqdm import tqdm
human_files_short = human_files[:100]
dog_files_short = dog_files[:100]
#-#-# Do NOT modify the code above this line. #-#-#
## TODO: Test the performance of the face_detector algorithm
F_1 = 0
D_1 =0
for i in range(100):
if face_detector(human_files_short[i]):
F_1+=1
if face_detector(dog_files_short[i]):
D_1+=1
print("right face in human_files_short is {}%".format(F_1))
print("right face in Dog_files_short is {}%".format(D_1))
## on the images in human_files_short and dog_files_short.
建议在算法中使用 OpenCV 的人脸检测器来检测人脸图像,但是你也可以尝试其他方法,尤其是利用深度学习的方法:)。请在以下代码单元格中设计并测试你的人脸检测算法。如果你打算完成此_可选_任务,请报告 human_files_short 和 dog_files_short 的效果。
### (Optional)
### TODO: Test performance of anotherface detection algorithm.
### Feel free to use as many code cells as needed.
import torch
import torchvision.models as models
# define VGG16 model
VGG16 = models.vgg16(pretrained=True)
# check if CUDA is available
use_cuda = torch.cuda.is_available()
# move model to GPU if CUDA is available
if use_cuda:
VGG16 = VGG16.cuda()
from PIL import Image
import torchvision.transforms as transforms
import cv2
如果给定一张图像,此预训练的 VGG-16 模型能够针对图像中的对象返回预测结果(属于 ImageNet 中的 1000 个潜在类别之一)。
在下个代码单元格中,你将编写一个函数,它将图像路径(例如 'dogImages/train/001.Affenpinscher/Affenpinscher_00001.jpg')当做输入,并返回预训练 VGG-16 模型预测的 ImageNet 类别对应的索引。输出应该始终是在 0 - 999(含)之间的整数。
在编写该函数之前,请阅读此 PyTorch 文档,了解如何针对预训练的模型预处理张量。
def VGG16_predict(img_path):
'''
Use pre-trained VGG-16 model to obtain index corresponding to
predicted ImageNet class for image at specified path
Args:
img_path: path to an image
Returns:
Index corresponding to VGG-16 model's prediction
'''
img = Image.open(img_path)
transform = transforms.Compose([
transforms.Resize((224,224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
img = transform(img)
img = torch.unsqueeze(img,0)
if use_cuda:
#data, target = data.cuda(), target.cuda()
img = img.cuda()
output=VGG16(img)
_, preds_tensor = torch.max(output, 1)
preds = np.squeeze(preds_tensor.numpy()) if not use_cuda else np.squeeze(preds_tensor.cpu().numpy())
return preds
VGG16_predict(dog_files[100])
### returns "True" if a dog is detected in the image stored at img_path
def dog_detector(img_path):
## TODO: Complete the function.
num = VGG16_predict(img_path)
if num>=151 and num<=268:
return True # true/false
else:
return None
问题 2:在以下代码单元格中测试 dog_detector 的效果。
human_files_short 中的图像,有多少图像检测到了小狗? dog_files_short 中的图像,有多少图像检测到了小狗?答案:
### TODO: Test the performance of the dog_detector function
### on the images in human_files_short and dog_files_short.
human_dectect_dog = 0
dog_dectect_dog = 0
for i in human_files_short:
if dog_detector(i):
human_dectect_dog+=1
else:
pass
for i in dog_files_short:
if dog_detector(i):
dog_dectect_dog+=1
else:
pass
print("the number of picture in human_files_short where dog is dectected is {}".format(human_dectect_dog))
print("the number of picture in dog_files_short where dog is dectected is {}".format(dog_dectect_dog))
建议在算法中使用 VGG-16 检测小狗图像,但是你也可以尝试其他预训练的网络(例如 Inception-v3、ResNet-50 等)。请在以下代码单元格中测试其他预训练的 PyTorch 模型。如果你打算完成此_可选_任务,请报告 human_files_short 和 dog_files_short 的效果。
ResNet_50 = models.resnet18(pretrained = True)
if use_cuda:
ResNet_50 = ResNet_50.cuda()
print(ResNet_50)
def ResNet_50_predict(img_path):
img = cv2.imread(img_path)
transform = transforms.Compose([
transforms.ToPILImage(),
transforms.Resize((224,224)),
transforms.ToTensor(),
transforms.Normalize(mean = [0.485, 0.456, 0.406],
std = [0.229, 0.224, 0.225])
])
image = transform(img)
image = torch.unsqueeze(image, 0)
if use_cuda:
image = image.cuda()
output = ResNet_50(image)
_, preds_tensor = torch.max(output, 1)
preds = np.squeeze(preds_tensor.numpy()) if not use_cuda else np.squeeze(preds_tensor.cpu().numpy())
return preds
ResNet_50_predict(dog_files[2])
def dog_detector(img_path):
## TODO: Complete the function.
num = ResNet_50_predict(img_path)
if num>=151 and num<=268:
return True # true/false
else:
return None
human_dectect_dog = 0
dog_dectect_dog = 0
for i in human_files_short:
if dog_detector(i):
human_dectect_dog+=1
else:
pass
for i in dog_files_short:
if dog_detector(i):
dog_dectect_dog+=1
else:
pass
print("the number of picture in human_files_short where dog is dectected is {}".format(human_dectect_dog))
print("the number of picture in dog_files_short where dog is dectected is {}".format(dog_dectect_dog))
创建好从图像中检测人脸和小狗的函数后,我们需要预测图像中的小狗品种。在这一步,你需要创建一个分类小狗品种的 CNN。你必须从头创建一个 CNN(因此暂时不能使用迁移学习。),并且测试准确率必须至少达到 10%。在此 notebook 的第 4 步,你将使用迁移学习创建 CNN,并且能够获得很高的准确率。
预测图中小狗的品种是一项非常难的挑战。说实话,即使是我们人类,也很难区分布列塔尼猎犬和威尔斯激飞猎犬。
| 布列塔尼猎犬 | 威尔斯激飞猎犬 |
|---|---|
![]() |
![]() |
还有很多其他相似的狗品种(例如卷毛寻回犬和美国水猎犬)。
| 卷毛寻回犬 | 美国水猎犬 |
|---|---|
![]() |
![]() |
同理,拉布拉多有黄色、巧克力色和黑色品种。基于视觉的算法需要克服这种同一类别差异很大的问题,并决定如何将所有这些不同肤色的小狗分类为相同的品种。
| 黄色拉布拉多 | 巧克力色拉布拉多 | 黑色拉布拉多 |
|---|---|---|
![]() |
![]() |
![]() |
随机猜测的效果很差:除了类别数量不太平衡之外,随机猜测的正确概率约为 1/133,准确率不到 1%。
在深度学习领域,实践比理论知识靠谱得到。请尝试多种不同的架构,并相信你的直觉。希望你可以从学习中获得乐趣!
在以下代码单元格中编写三个独立的数据加载器,用于训练、验证和测试小狗图像数据集(分别位于 dog_images/train、dog_images/valid 和 dog_images/test 下)。此自定义数据集文档或许对你有帮助。如果你想增强训练和/或验证数据,请参阅各种转换方法!
import torch
use_cuda = torch.cuda.is_available()
import os
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
### TODO: Write data loaders for training, validation, and test sets
## Specify appropriate transforms, and batch_sizes
train_transform = transforms.Compose([
transforms.Resize((224,224)),
transforms.RandomHorizontalFlip(),
transforms.RandomRotation(20),
transforms.ToTensor(),
transforms.Normalize(mean = [0.5,0.5,0.5], std = [0.5, 0.5,0.5])
]
)
Image_train = datasets.ImageFolder("/data/dog_images/train", transform = train_transform)
#print(Image_train.class_to_idx)
train_loader = DataLoader(Image_train,
batch_size=15,
shuffle=True)
val_transform = transforms.Compose(
[
transforms.Resize((224,224)),
transforms.ToTensor(),
transforms.Normalize(mean = [0.5,0.5,0.5],std = [0.5, 0.5, 0.5])
]
)
Image_val = datasets.ImageFolder("/data/dog_images/valid", transform = val_transform)
#print(Image_val.class_to_idx)
val_loader = DataLoader(Image_val,
batch_size=15,
shuffle =True)
test_transform = transforms.Compose([
transforms.Resize((224,224)),
transforms.ToTensor(),
transforms.Normalize(mean = [0.5, 0.5, 0.5],std = [0.5, 0.5, 0.5])
])
Image_test = datasets.ImageFolder("/data/dog_images/test", transform = test_transform)
test_loader = DataLoader(Image_test,
batch_size = 15,
shuffle= True)
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
classes = list(Image_train.class_to_idx.keys())
#print(classes)
# helper function to un-normalize and display an image
def imshow(img):
img = img / 3 + 0.5 # unnormalize
plt.imshow(np.transpose(img, (1, 2, 0)))
dataiter = iter(train_loader)
images,labels = dataiter.next()
image = images.numpy()
fig = plt.figure(figsize = (50,50))
for idx in range(30):
ax = fig.add_subplot(6, 30/6, idx+1, xticks=[], yticks=[])
imshow(images[idx])
print(labels[0])
ax.set_title(classes[labels[idx]])
问题 3:描述你所选的数据预处理流程。
答案:
创建分类小狗品种的 CNN。使用以下代码单元格中的模板。
import torch.nn as nn
import torch.nn.functional as F
# define the CNN architecture
class Net(nn.Module):
### TODO: choose an architecture, and complete the class
def __init__(self):
super(Net, self).__init__()
## Define layers of a CNN
self.conv1 = nn.Conv2d(3,64,3 ,padding=1)
self.conv2 = nn.Conv2d(64,128,3, padding=1)
self.conv3 = nn.Conv2d(128,256,3,padding=1)
self.conv4 = nn.Conv2d(256,512,3,padding=1)
self.conv5 = nn.Conv2d(512,512,3,padding=1)
self.dropout = nn.Dropout(0.3)
self.pool = nn.MaxPool2d(2,2)
self.fc1 = nn.Linear(7*7*512,2048)
self.fc2 = nn.Linear(2048,512)
self.fc3 = nn.Linear(512,133)
def forward(self, x):
## Define forward behavior
#x=x.view(-1,224*224*3)
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x= self.pool(F.relu(self.conv3(x)))
x = self.pool(F.relu(self.conv4(x)))
x = self.pool(F.relu(self.conv5(x)))
x = x.view(x.size(0),-1)
x = self.dropout(x)
x = self.fc1(x)
x = self.dropout(x)
x = self.fc2(x)
x = self.dropout(x)
x = self.fc3(x)
return x
#-#-# You so NOT have to modify the code below this line. #-#-#
# instantiate the CNN
model_scratch = Net()
# move tensors to GPU if CUDA is available
if use_cuda:
model_scratch.cuda()
print(model_scratch)
import torch.optim as optim
### TODO: select loss function
criterion_scratch = nn.CrossEntropyLoss()
### TODO: select optimizer
optimizer_scratch = optim.SGD(model_scratch.parameters(),lr=0.001)
loaders_scratch = {'train':train_loader,
'valid':val_loader,
'test':test_loader}
from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
import numpy as np
def train(n_epochs, loaders, model, optimizer, criterion, use_cuda, save_path):
"""returns trained model"""
# initialize tracker for minimum validation loss
valid_loss_min = np.Inf
for epoch in range(1, n_epochs+1):
# initialize variables to monitor training and validation loss
train_loss = 0.0
valid_loss = 0.0
###################
# train the model #
###################
model.train()
for batch_idx, (data, target) in enumerate(loaders['train']):
# move to GPU
if use_cuda:
data, target = data.cuda(), target.cuda()
## find the loss and update the model parameters accordingly
## record the average training loss, using something like
## train_loss = train_loss + ((1 / (batch_idx + 1)) * (loss.data - train_loss))
optimizer.zero_grad()
output = model(data)
loss = criterion(output,target)
loss.backward()
optimizer.step()
train_loss = loss.item()*data.size(0)
######################
# validate the model #
######################
model.eval()
for batch_idx, (data, target) in enumerate(loaders['valid']):
# move to GPU
if use_cuda:
data, target = data.cuda(), target.cuda()
## update the average validation loss
output = model(data)
loss = criterion(output,target)
valid_loss = loss.item()*data.size(0)
train_loss = train_loss/len(loaders['train'].dataset)
valid_loss = valid_loss/len(loaders['valid'].dataset)
# print training/validation statistics
print('Epoch: {} \tTraining Loss: {:.6f} \tValidation Loss: {:.6f}'.format(
epoch,
train_loss,
valid_loss
))
## TODO: save the model if validation loss has decreased
if valid_loss < valid_loss_min:
print("the valid_loss has decreased ({:.6f}--->{:.6f})".format(valid_loss_min,valid_loss))
torch.save(model.state_dict(),save_path)
valid_loss_min = valid_loss
else:
print("the better epoch is {}".format(epoch))
return model
# return trained model
return model
# train the model
model_scratch = train(40, loaders_scratch, model_scratch, optimizer_scratch,
criterion_scratch, use_cuda, 'model_scratch.pt')
# load the model that got the best validation accuracy
model_scratch.load_state_dict(torch.load('model_scratch.pt'))
在小狗图像测试数据集上尝试模型。在以下代码单元格中计算并输出测试损失和准确率。确保测试准确率高于 10%。
def test(loaders, model, criterion, use_cuda):
# monitor test loss and accuracy
test_loss = 0.
correct = 0.
total = 0.
model.eval()
for batch_idx, (data, target) in enumerate(loaders['test']):
# move to GPU
if use_cuda:
data, target = data.cuda(), target.cuda()
# forward pass: compute predicted outputs by passing inputs to the model
output = model(data)
# calculate the loss
loss = criterion(output, target)
# update average test loss
test_loss = test_loss + ((1 / (batch_idx + 1)) * (loss.data - test_loss))
# convert output probabilities to predicted class
pred = output.data.max(1, keepdim=True)[1]
# compare predictions to true label
correct += np.sum(np.squeeze(pred.eq(target.data.view_as(pred))).cpu().numpy())
total += data.size(0)
print('Test Loss: {:.6f}\n'.format(test_loss))
print('\nTest Accuracy: %2d%% (%2d/%2d)' % (
100. * correct / total, correct, total))
# call test function
test(loaders_scratch, model_scratch, criterion_scratch, use_cuda)
import os
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
## TODO: Specify data loaders
data_transform={
'train':transforms.Compose([
transforms.Resize((224,224)),
transforms.RandomRotation(20),
transforms.ToTensor(),
transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
]),
'valid':transforms.Compose([
transforms.Resize((224,224)),
transforms.ToTensor(),
transforms.Normalize([0.5,0.5,0.5], [0.5,0.5,0.5])
]),
'test':transforms.Compose([
transforms.Resize((224,224)),
transforms.ToTensor(),
transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
])}
train_image = datasets.ImageFolder("/data/dog_images/train", transform = data_transform['train'])
train_loader = DataLoader(train_image,
batch_size =20,
shuffle=True)
test_image = datasets.ImageFolder("/data/dog_images/test",transform = data_transform['test'])
test_loader = DataLoader(test_image,
batch_size = 20,
shuffle=True)
valid_image = datasets.ImageFolder("/data/dog_images/valid", transform=data_transform['valid'])
valid_loader = DataLoader(valid_image,
batch_size =20,
shuffle = True)
使用迁移学习创建分类小狗品种的 CNN。在以下代码单元格中填写代码并将初始化的模型另存为变量 model_transfer。
import torchvision.models as models
import torch.nn as nn
## TODO: Specify model architecture
vgg16 = models.vgg16(pretrained=True)
#if use_cuda:
# model_transfer = model_transfer.cuda()
print(vgg16)
for param in vgg16.features.parameters():
param.requires_grad = False
import torch
use_cuda = torch.cuda.is_available()
for param in vgg16.features.parameters():
param.requires_grad = False
input_node = vgg16.classifier[6].in_features
fc2 = nn.Linear(input_node,133)
vgg16.classifier[6] = fc2
print(vgg16)
if use_cuda:
vgg16.cuda()
import torch.optim as optim
criterion_transfer = nn.CrossEntropyLoss()
optimizer_transfer = optim.SGD(vgg16.classifier.parameters(), lr=0.001)
#optimizer_transfer = optim.SGD(filter(lambda p: p.requires_grad,vgg16.parameters()), lr = 0.01)
from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
# train the model
loaders_transfer = {"train":train_loader,
"test":test_loader,
"valid":valid_loader}
model_transfer = vgg16
n_epochs = 10
model_transfer = train(n_epochs, loaders_transfer, model_transfer, optimizer_transfer, criterion_transfer, use_cuda, 'model_transfer.pt')
# load the model that got the best validation accuracy (uncomment the line below)
model_transfer.load_state_dict(torch.load('model_transfer.pt'))
在小狗图像测试数据集上尝试模型。在以下代码单元格中计算并输出测试损失和准确率。确保测试准确率高于 60%。
test(loaders_transfer, model_transfer, criterion_transfer, use_cuda)
编写一个函数,它会将图像路径作为输入,并返回模型预测的小狗品种(Affenpinscher、Afghan hound 等)。
def VGG16_predict(img_path):
'''
Use pre-trained VGG-16 model to obtain index corresponding to
predicted ImageNet class for image at specified path
Args:
img_path: path to an image
Returns:
Index corresponding to VGG-16 model's prediction
'''
## TODO: Complete the function.
## Load and pre-process an image from the given img_path
## Return the *index* of the predicted class for that image
img = cv2.imread(img_path)
#img = img.transpose(2,0,1)
#img = np.expand_dims(img,axis=0)
transform = transforms.Compose([
transforms.ToPILImage(),
transforms.Resize((224,224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
img_1 = transform(img)
img_1 = torch.unsqueeze(img_1, 0)
if use_cuda:
#data, target = data.cuda(), target.cuda()
img_1 = img_1.cuda()
classNum=VGG16(img_1)
#T = torch.max(classNum_0, 1)
#classNum = T[1].numpy()
#np.argmax(predicted_vector)
return np.argmax(classNum.cpu().detach().numpy())
# predicted class index
### TODO: Write a function that takes a path to an image as input
### and returns the dog breed that is predicted by the model.
from PIL import Image
import torch
# list of class names by index, i.e. a name can be accessed like class_names[0]
#class_names = [item[4:].replace("_", " ") for item in data_transfer['train'].classes]
def predict_breed_transfer(img_path):
# load the image and return the predicted breed
img = Image.open(img_path)
img = data_transform['test'](img)
img = torch.unsqueeze(img,0)
if use_cuda:
img = img.cuda()
output = model_transfer(img)
_, preds_tensor = torch.max(output, 1)
preds = np.squeeze(preds_tensor.numpy()) if not use_cuda else np.squeeze(preds_tensor.cpu().numpy())
class_names = [item[4:].replace("_", " ") for item in train_image.classes]
return class_names[preds]
predict_breed_transfer(dog_files[0])
### TODO: Write your algorithm.
### Feel free to use as many code cells as needed.
import cv2
def run_app(img_path):
## handle cases for a human face, dog, and neither
if face_detector(img_path):
output = predict_breed_transfer(img_path)
img = cv2.imread(img_path)
fig,ax=plt.subplots(1,1)
plt.imshow(img)
ax.set_title('hello human and you look like a ....'+output)
plt.show()
elif dog_detector(img_path):
output = predict_breed_transfer(img_path)
img = cv2.imread(img_path)
fig,ax=plt.subplots(1,1)
plt.imshow(img)
ax.set_title('this is a dog and its type is'+output)
plt.show()
else:
print('there is nothing detected')
在此部分测试新算法啦。算法认为看起来像哪种小狗?如果你有一只狗,算法能准确预测出小狗的品种吗?如果你有一只猫,算法会错误地认为这只猫是小狗吗?
至少在计算机上用 6 张图像测试你的算法。你可以使用任何图像。至少测试两张人脸图像和两张小狗图像。
问题 6:结果比你预期的要好吗 :)?还是更糟糕 :(?请对你的算法提出至少三个值得改进的地方。
__答案:预期的要好,
## TODO: Execute your algorithm from Step 6 on
## at least 6 images on your computer.
## Feel free to use as many code cells as needed.
## suggested code, below
for file in np.hstack((human_files[:3], dog_files[:3])):
run_app(file)
for file in np.hstack((human_files[:3], dog_files[:3])):
run_app(file)